import fs from "fs";
import path from "path";
import { z } from "zod";

export interface LlmEnvConfig {
    baseUrl: string;
    apiKey: string;
    model: string;
}

export interface McpEnvConfig {
    mcpFilePath: string;
}

export interface AgentDefineEnvConfig {
    llmName: string;
    mcpName: string;
}

export interface AgentEnvConfig {
    define: AgentDefineEnvConfig;
    mcp: Record<string, McpEnvConfig>;
    llm: Record<string, LlmEnvConfig>;
}

const AgentConfigSchema = z.object({
  define: z.object({
    "llmName": z.string().min(1),
    "mcpName": z.string().min(1)
  }).transform(def => ({
    llmName: def["llmName"],
    mcpName: def["mcpName"]
  })),
  mcp: z.record(z.string(), z.object({
    mcpFilePath: z.string().min(1)
  })),
  llm: z.record(z.string(), z.object({
    baseUrl: z.string().url(),
    apiKey: z.string().min(10),
    model: z.string()
  }))
}) satisfies z.ZodType<AgentEnvConfig>;

class EnvConfig {
    public agentConfig: AgentEnvConfig;
    public llmConfig: LlmEnvConfig;
    public mcpConfig: McpEnvConfig;

    private constructor(agentConfig: AgentEnvConfig, llmConfig: LlmEnvConfig, mcpConfig: McpEnvConfig) {
        this.agentConfig = agentConfig;
        this.llmConfig = llmConfig;
        this.mcpConfig = mcpConfig;
    }

    static loadEnvConfig(): EnvConfig {
        const configFilePath: string = process.env.LLM_CONFIG_FILE_PATH as string;
        const llmName: string = process.env.LLM_NAME as string;
        const mcpName: string = process.env.MCP_NAME as string;
        const rawData = fs.readFileSync(path.resolve(configFilePath), 'utf-8');
        const jsonData = JSON.parse(rawData);
        const agentConfig: AgentEnvConfig = AgentConfigSchema.parse(jsonData);
        const llmConfig: LlmEnvConfig = agentConfig.llm[llmName];
        const mcpConfig: McpEnvConfig = agentConfig.mcp[mcpName];
        return new EnvConfig(agentConfig, llmConfig, mcpConfig);;
    }
}

export const agentEnv = EnvConfig.loadEnvConfig();